/*

This file is part of Rooms3D.

Copyright (C) 2008 Pixecur Technologies Incorporated (Esotera).
Visit Esotera at http://www.esoteras3.com
 
Rooms3D is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
 
Rooms3D is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with Rooms3D; see the file COPYING.  If not, write to 
Pixecur Technologies, 213-31 Peet Street, St. John's, NL, A1B 3W8. 
 
Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
 
*/
// Win32Utils.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"
#include "Win32Utils.h"



#include "ThumbnailExtractor.h"






WIN32UTILS_API BOOL OpenFileInDefaultEditor(LPCWSTR fileName)
{
	return ExecuteShellCommand(fileName, NULL, NULL);
}

WIN32UTILS_API BOOL ExecuteShellCommand(LPCWSTR command, LPCWSTR workingDirectory, LPCWSTR parameters)
{
	CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);


    BOOL nResult;
    DWORD dwErr;
    HRESULT hr;
    PARSEDURL pu;
    TCHAR szSchemeBuffer[INTERNET_MAX_SCHEME_LENGTH + 1];
    HKEY hkeyClass;

	SHELLEXECUTEINFO SHInfo = {0};

    /* Default error codes */

    nResult = FALSE;
    dwErr = ERROR_INVALID_PARAMETER;
    hr = S_OK;
    SHInfo.hInstApp =
        (HINSTANCE)UlongToHandle(SE_ERR_ACCESSDENIED);

	SHInfo.cbSize = sizeof (SHELLEXECUTEINFO);
	SHInfo.fMask = SEE_MASK_NOASYNC | SEE_MASK_FLAG_NO_UI | SEE_MASK_WAITFORINPUTIDLE;
	//SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI | ;
	SHInfo.lpVerb = NULL;//_T ("open");
	//SHInfo.lpFile = _T ("d:\\Temp\\upload\\video.dvr-ms");
	SHInfo.lpFile = command;//"d:\\Temp\\upload\\a b\\Bear 10.wmv");
	SHInfo.lpDirectory = workingDirectory;
	SHInfo.lpParameters = parameters;
	//SHInfo.lpParameters = NULL;// _T ("Additional Parameters or NULL if the parameter above is not an application");
	SHInfo.nShow = SW_SHOW;


	pu.cbSize = sizeof(pu);
    hr = ParseURL(command, &pu);

        /* Is the URL really, unambiguously an URL? */
    if(SUCCEEDED(hr) && pu.pszProtocol == command &&
            pu.pszProtocol[pu.cchProtocol] == TEXT(':'))
    {
        /* We need the scheme name NUL-terminated, so we copy it */
        hr = StringCbCopyN (szSchemeBuffer, sizeof(szSchemeBuffer),
            pu.pszProtocol, pu.cchProtocol * sizeof(TCHAR));
		
        if(SUCCEEDED(hr))
        {
            /* Is the URL scheme a registered ProgId? */
            hr = AssocQueryKey(ASSOCF_INIT_IGNOREUNKNOWN,
                ASSOCKEY_CLASS, szSchemeBuffer,
                NULL, &hkeyClass);

            if(SUCCEEDED(hr))
            {
                /* Is the ProgId really an URL scheme? */
                dwErr = RegQueryValueEx(hkeyClass,
                    TEXT("URL Protocol"), NULL,
                    NULL, NULL, NULL
                );

                /* All clear! */
                if(dwErr == NO_ERROR || dwErr == ERROR_MORE_DATA)
                {
                    /* Don't let ShellExecuteEx guess */
                    SHInfo.fMask |= SEE_MASK_CLASSKEY;
                    SHInfo.lpClass = NULL;
                    SHInfo.hkeyClass = hkeyClass;
                    nResult = ShellExecuteEx(&SHInfo);
                    /* To preserve ShellExecuteEx's last error */
                    dwErr = NO_ERROR;
                }
                RegCloseKey(hkeyClass);
				CoUninitialize();
				return nResult;
            }
		}
	}

    SHInfo.fMask &= ~SEE_MASK_CLASSKEY;
    SHInfo.lpClass = NULL;
    SHInfo.hkeyClass = NULL;

	nResult = ShellExecuteEx (&SHInfo);

	CoUninitialize();


	return nResult;
}


/*
	--	Thumbnail extraction interfaces	--
*/




WIN32UTILS_API  BOOL ExtractFileThumbnail(LPCWSTR fileName, BOOL isLargeThumbnail, long *pBufferSize, char* pngBuffer)
{
	CThumbnailExtractor thumbnailExtractor;
	
	int dimension = isLargeThumbnail? 256 : 128;
	

	long bufferSize = *pBufferSize;
	//char* pngBuffer = NULL;
	
	HRESULT result = thumbnailExtractor.ExtractFileThumbnailIntoPNG(fileName, dimension, dimension, 16, bufferSize, pngBuffer);
	
	*pBufferSize = bufferSize;

	//printf("large=%d; bufferSize = %u\r\n", isLargeThumbnail, bufferSize);
	//std::cout<<"large = " << large;

	//Code to test the contents of the output buffer
	/*
	HANDLE fHandle = CreateFile(L"C:\\Temp\\Output_stream_3.png", 
		FILE_WRITE_DATA,
		FILE_WRITE_DATA,
		NULL,
		CREATE_ALWAYS,
		FILE_ATTRIBUTE_ARCHIVE, 
		NULL);

	DWORD writtenSize = 0;
	BOOL bWriteResult = WriteFile(fHandle, pngBuffer, bufferSize, &writtenSize, NULL);
	BOOL bCloseResult = CloseHandle(fHandle); 
	*/
	

	if(FAILED(result))
		return FALSE;

	return TRUE;
}



WIN32UTILS_API BOOL SetProcessPriorityBelowNormal()
{
	HANDLE hCurrentProcess = GetCurrentProcess();
	BOOL bResult = SetPriorityClass(hCurrentProcess, BELOW_NORMAL_PRIORITY_CLASS);

	return bResult;
}

WIN32UTILS_API BOOL SetProcessPriorityNormal()
{
	HANDLE hCurrentProcess = GetCurrentProcess();
	BOOL bResult = SetPriorityClass(hCurrentProcess, NORMAL_PRIORITY_CLASS);

	return bResult;
}

WIN32UTILS_API BOOL SetProcessPriorityAboveNormal()
{
	HANDLE hCurrentProcess = GetCurrentProcess();
	BOOL bResult = SetPriorityClass(hCurrentProcess, ABOVE_NORMAL_PRIORITY_CLASS);

	return bResult;
}

WIN32UTILS_API DWORD GetCurrentProcessNumericId()
{
	return GetCurrentProcessId();
}


/*
 * Class:     org_alfresco_jlan_util_win32_Win32Utils
 * Method:    SetWorkingSetSize
 * Signature: (JJ)Z
 */
WIN32UTILS_API BOOL SetWorkingSetSize
	(DWORD jminBytes, DWORD jmaxBytes) {

	/*
	 * Get the current process handle
	 */
	
	HANDLE thisProcess = GetCurrentProcess();

	/*
	 * Set the working set size for the Java process
	 */

	return SetProcessWorkingSetSize(thisProcess, (DWORD) jminBytes, (DWORD) jmaxBytes);
}

/*
 * Class:     org_alfresco_jlan_util_win32_Win32Utils
 * Method:    MapNetworkDrive
 * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZ)Z
 */
WIN32UTILS_API int MapNetworkDrive
  (LPCWSTR remPath, LPCWSTR localPath, LPCWSTR userName, LPCWSTR password,
  BOOL jinteractive, BOOL jprompt) {


	int flags = 0;
	int sts;

	NETRESOURCE netRsc;

	/*
	 *	Populate the NETRESOURCE structure
	 */

	memset(&netRsc, 0, sizeof(netRsc));

	netRsc.dwType       = RESOURCETYPE_DISK;
	netRsc.lpLocalName  = (LPWSTR) localPath;
	netRsc.lpRemoteName = (LPWSTR) remPath;
	netRsc.lpProvider   = NULL;

	/*
	 * Set various option flags for the connection
	 */

	if ( jinteractive)
		flags += CONNECT_INTERACTIVE;

	if ( jprompt)
		flags += CONNECT_PROMPT;

	/*
	 * Map the network drive
	 */

	sts = WNetAddConnection2(&netRsc, password, userName, flags);


	return sts;
}

WIN32UTILS_API int GetNetworkDriveRemotePath(LPCWSTR lpLocalName, char* remoteNameBuffer, int* length) 
{
	wchar_t* remoteName = new wchar_t[*length * 2 + 1];

	DWORD retLength = *length;

	int status = WNetGetConnection(lpLocalName, remoteName, &retLength); 

	*length = wcstombs(remoteNameBuffer, remoteName, retLength);
	
	delete remoteName;

	return status;
}


/*
 * Class:     org_alfresco_jlan_util_win32_Win32Utils
 * Method:    DeleteNetworkDrive
 * Signature: (Ljava/lang/String;ZZ)I
 */
WIN32UTILS_API int DeleteNetworkDrive
( LPCWSTR devName, BOOL jupdProfile, BOOL jforce) {


	int flags = 0;
	int sts;


	/*
	 * Set the flags
	 */

	if ( jupdProfile)
		flags += CONNECT_UPDATE_PROFILE;

	/*
	 * Disconnect the mapped drive
	 */

	sts = WNetCancelConnection2(devName, flags, jforce);

	/*
	 * Return the unmap drive status
	 */

	return sts;
}


